package org.alex.farouq.exam.controller.question;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

import org.alex.farouq.exam.model.question.Question;

/**
 * 
 * @author Ahmed Abdelkader
 */
public class ExamModelGenerator {

	class Q implements Comparable<Q> {
		int id;
		int score;
		public Q(int id) {
			this.id = id;
		}
		public void inc() {
			this.score++;
		}
		public int compareTo(Q q) {
			return score - q.score;
		}
	}
	
	public static class Exam extends ArrayList<Integer> {
		private static final long serialVersionUID = 1L;
		Question[] questionsArray;
		Exam(Question[] questionsArray) {
			this.questionsArray = questionsArray;
		}
		public Question[] getQuestions() {
			Question[] questions = new Question[this.size()];
			for (int i = 0; i < questions.length; i++)
				questions[i] = questionsArray[this.get(i)];
			return questions;
		}
		public int diff(Exam e) {
			int r = 0;
			for (int i = 0, j = 0; i < this.size() || j < e.size();) {
				int a = i == this.size()? -1 : this.get(i);
				int b = j == e.size()? -1 : e.get(j);
				if (a == -1) {
					j++;
					r++;
				}
				else if (b == -1) {
					i++;
					r++;
				}
				else if (a < b) {
					i++;
					r++;
				} else if (a > b) {
					j++;
					r++;
				} else {
					i++;
					j++;
				}
			}
			return r / 2;
		}
	}
	
	public Collection<Exam> generateExamModelUsingQuestions(Question[] questionsArray,int numberOfModels,int numberOfQuestionsPerModel)
	{
		ArrayList<Exam> exams = new ArrayList<Exam>();
		ArrayList<Q> db = new ArrayList<Q>();
		for (int i = 0; i < questionsArray.length; i++) db.add(new Q(i));
		for (int i = 0; i < numberOfModels; i++) {
			Collections.shuffle(db);
			Collections.sort(db);
			Exam e = new Exam(questionsArray);
			for (int j = 0; j < numberOfQuestionsPerModel; j++) {
				e.add(db.get(j).id);
				db.get(j).inc();
			}
			Collections.sort(e);
			int minD = numberOfQuestionsPerModel;
			for (Exam ee : exams)
				minD = Math.min(minD, e.diff(ee));
			if (minD > 0)
				exams.add(e);
			else
				i--;
		}
		return exams;
	}
}
